<template>
  <a-table
    :class="tableClass"
    :bordered="bordered"
    :loading="loadingV"
    :columns="columns"
    :data-source="list"
    :row-key="rowKey"
    table-layout="fixed"
    v-bind="$attrs"
    :pagination="pagination"
    :row-selection="
      checkEnable ? { selectedRowKeys: selectedRowKeys, onChange: onSelectChange } : null
    "
    @resizeColumn="
      (w, col) => {
        col.width = w
      }
    "
    @change="handleTableChange"
  >
    <template v-for="item in renderArr" #[item]="scope">
      <slot :name="item" :scope="scope" v-bind="scope || {}"></slot>
    </template>
  </a-table>
</template>
<script>
import { reactive, useSlots, toRefs } from 'vue'
export default {
  name: 'STable',
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    bordered: Boolean,
    columns: Array,
    tableClass: {
      default: 'skrivet-table'
    },
    rowKey: {
      type: [String, Function],
      default: 'id'
    },
    checkEnable: {
      type: Boolean,
      required: false,
      default: true
    },
    value: {
      type: Array,
      required: false,
      default: undefined
    },
    initParam: {
      type: Object,
      required: false
    },
    url: String,
    pageable: {
      type: Boolean,
      default: true
    },
    loadInit: {
      type: Boolean,
      default: true
    },
    loading: {
      type: Boolean,
      default: false
    },
    // 格式:{name:'',label:'',value:'',url:''}
    echos: {
      type: Array,
      required: false,
      default: () => {
        return []
      }
    },
    pullData: {
      type: Function,
      required: false
    }
  },
  emits: ['change'],
  setup(props, { emit }) {
    const slots = useSlots()
    const renderArr = Object.keys(slots)
    const data = reactive({
      renderArr
    })
    return {
      ...toRefs(data)
    }
  },
  data() {
    return {
      list: this.value,
      loadingV: this.loading,
      param: {},
      dicts: {},
      selectedRows: [],
      selectedRowKeys: [],
      queryCache: {},
      pagination: this.pageable
        ? {
            current: 1,
            pageSize: 10,
            pageSizeOptions: ['10', '20', '50', '100'],
            showSizeChanger: true,
            showQuickJumper: true,
            total: 0
          }
        : false
    }
  },
  watch: {
    url: {
      handler: function (val, oldVal) {
        this.search()
      },
      immediate: true
    },
    loading: {
      handler: function (val, oldVal) {
        this.loadingV = val
      },
      immediate: true
    },
    value: {
      handler: function (val, oldVal) {
        this.list = val
        if (this.echos && this.echos.length > 0) {
          const all = []
          this.echos.forEach((item) => {
            all.push(this.$api.GET(item.url))
          })
          Promise.all(all).then((allRes) => {
            let i = 0
            allRes.forEach((res) => {
              const item = this.echos[i]
              if (res.data) {
                const labelKey = item.label ? item.label : 'text'
                const valueKey = item.value ? item.value : 'value'
                const result = []
                res.data.forEach((item) => {
                  result.push({
                    text: item[labelKey],
                    value: item[valueKey]
                  })
                })
                this.dicts[item.name] = result
              }
              i++
            })
            if (this.list) {
              this.list.forEach((data) => {
                this.echos.forEach((echo) => {
                  const name = echo.name
                  const val = data[name]
                  const echoName = name + 'Name'
                  let echoValue
                  if (val) {
                    const dictList = this.dicts[name]
                    const p = dictList.find((a) => a.value == val)
                    echoValue = p ? p.text : undefined
                  }
                  this.list.data[echoName] = echoValue
                })
              })
            }
          })
        }
      },
      deep: true
    },
    echos: {
      handler: function (val, oldVal) {
        if (this.echos && this.echos.length > 0) {
          const all = []
          this.echos.forEach((item) => {
            all.push(this.$api.GET(item.url))
          })
          Promise.all(all).then((allRes) => {
            let i = 0
            allRes.forEach((res) => {
              const item = this.echos[i]
              if (res.data) {
                const labelKey = item.label ? item.label : 'text'
                const valueKey = item.value ? item.value : 'value'
                const result = []
                
                if(item.type) {
                  res.data[item.type].forEach((item) => {
                    result.push({
                      text: item[labelKey],
                      value: item[valueKey]
                    })
                  })
                } else {
                  res.data.forEach((item) => {
                    result.push({
                      text: item[labelKey],
                      value: item[valueKey]
                    })
                  })
                }
                this.dicts[item.name] = result
              }
              i++
            })
            if (this.list) {
              this.list.forEach((data) => {
                this.echos.forEach((echo) => {
                  const name = echo.name
                  const val = data[name]
                  const echoName = name + 'Name'
                  let echoValue
                  if (val) {
                    const dictList = this.dicts[name]
                    const p = dictList.find((a) => a.value == val)
                    echoValue = p ? p.text : undefined
                  }
                  data[echoName] = echoValue
                })
              })
            }
          })
        }
      },
      deep: true
    }
  },
  created() {
    if (this.loadInit) {
      this.init()
    }
  },
  methods: {
    init() {
      if (this.echos && this.echos.length > 0) {
        const all = []
        this.echos.forEach((item) => {
          all.push(this.$api.GET(item.url))
        })
        Promise.all(all).then((allRes) => {
          let i = 0
          allRes.forEach((res) => {
            const item = this.echos[i]
            if (res.data) {
              const labelKey = item.label ? item.label : 'text'
              const valueKey = item.value ? item.value : 'value'
              const result = []
              if(item.type) {
                res.data[item.type].forEach((item) => {
                  result.push({
                    text: item[labelKey],
                    value: item[valueKey]
                  })
                })
              } else {
                res.data.forEach((item) => {
                  result.push({
                    text: item[labelKey],
                    value: item[valueKey]
                  })
                })
              }
              this.dicts[item.name] = result
            }
            i++
          })
          if (this.url) {
            Object.assign(this.param, this.initParam)
            this.doPullData()
          }
        })
      } else {
        if (this.url) {
          Object.assign(this.param, this.initParam)
          this.doPullData()
        }
      }
    },
    onSelectChange(selectedRowKeys, selectedRows) {
      this.selectedRows = selectedRows
      this.selectedRowKeys = selectedRowKeys
    },
    getSelectedKeys() {
      return this.selectedRowKeys
    },
    getSelectedItem() {
      return this.selectedRows
    },
    handleTableChange(pagination, filters, sorter) {
      if (sorter && sorter.field) {
        this.queryCache.sort = sorter.field
        if (sorter.order === 'ascend') {
          this.queryCache.order = 'asc'
        } else if (sorter.order === 'descend') {
          this.queryCache.order = 'desc'
        }
      }
      if (this.pageable) {
        this.doPullData({ current: pagination.current, pageSize: pagination.pageSize }, () => {
          this.pagination.current = pagination.current
          this.pagination.pageSize = pagination.pageSize
        })
      } else {
        this.doPullData()
      }
    },
    search(param) {
      this.param = Object.assign({}, this.initParam)
      if (param) {
        for (const key in param) {
          this.param[key] = param[key]
        }
      }
      if (this.pageable) {
        this.pagination.current = 1
        this.pagination.pageSize = parseInt(this.pagination.pageSizeOptions[0])
      }
      this.doPullData()
    },
    refresh() {
      this.doPullData()
    },
    doPullData(page, callBack) {
      if (!this.url) {
        return
      }
      this.selectedRows = []
      this.selectedRowKeys = []
      const data = Object.assign({}, this.param, this.queryCache)
      if (this.pageable) {
        if (page) {
          data.page = page.current
          data.rows = page.pageSize
        } else {
          data.page = this.pagination.current
          data.rows = this.pagination.pageSize
        }
      }
      this.loadingV = true
      let promise = this.pullData ? this.pullData(data) : this.$api.GET(this.url, data)
      promise
        .then((res) => {
          this.loadingV = false
          if (res.code === this.CODES.SUCCESS) {
            const datas = res.data
            if (this.echos && this.echos.length > 0 && datas && datas.length > 0) {
              datas.forEach((data) => {
                this.echos.forEach((echo) => {
                  const name = echo.name
                  const val = data[name]
                  const echoName = name + 'Name'
                  let echoValue
                  if (val) {
                    const dictList = this.dicts[name]
                    const p = dictList.find((a) => a.value == val)
                    echoValue = p ? p.text : undefined
                  }
                  data[echoName] = echoValue
                })
              })
            }
            this.list = datas
            this.$emit('change', datas)
            if (this.pageable) {
              this.pagination.total = res.count
            }
            if (callBack) {
              callBack()
            }
          }
        })
        .catch(() => {
          this.loadingV = false
        })
    }
  }
}
</script>
